home *** CD-ROM | disk | FTP | other *** search
- (c) Copyright 1993 Commodore-Amiga, Inc. All rights reserved.
- The information contained herein is subject to change without notice,
- and is provided "as is" without warranty of any kind, either expressed
- or implied. The entire risk as to the use of this information is
- assumed by the user.
-
-
- Boopsi in Release 3
-
- by John Orr and Peter Cherna
-
-
-
- For Release 3, Intuition gained significant improvements that
- directly affect Intuition's object oriented programming subsystem,
- Boopsi. Intuition now has gadget help features, bounding boxes for
- gadgets and their imagery, special custom layout gadgetry, and
- several other features that all have an impact on Boopsi.
-
- This article assumes that the reader already has a basic
- understanding of Boopsi and the object oriented programming model.
- For those not comfortable with these concepts, see the
- ``Boopsi--Object Oriented Intuition'' chapter of the ROM Kernel
- Reference Manual: Libraries.
-
-
- DoGadgetMethodA()
-
- One Boopsi-related function added to intuition.library for Release 3
- is DoGadgetMethodA():
-
- ULONG DoGadgetMethodA(struct Gadget *object, struct Window *win,
- struct Requester *req, Msg msg);
-
- This function is similar to amiga.lib's DoMethod(), except
- DoGadgetMethod() passes along the object's graphical environment in
- the form of a GadgetInfo structure. DoGadgetMethodA() gets this
- structure from the gadget's window (or requester). The GadgetInfo
- structure is important because a Boopsi gadget needs the information
- in that structure to render itself. Note that if you give
- DoGadgetMethodA() a NULL Window and NULL Requester pointer,
- DoGadgetMethodA() will pass a NULL GadgetInfo pointer.
-
- The name and first parameter of DoGadgetMethodA() may lead you to
- believe that this function applies only to gadgets. Although you can
- certainly use this function on gadget objects, the function is not
- restricted to gadget objects. You can use this function on any
- Boopsi object. This is important for an object such as a model
- object, which may react to any Boopsi message by invoking some method
- on gadget objects connected to it. Because the model object receives
- environment information in the form of a GadgetInfo structure, the
- model can pass that information on to any objects connected to it.
-
- Before this function, passing the environment information was not
- that easy. A good example of this is the rkmmodelclass example in
- the ``Boopsi--Object Oriented Intuition'' chapter of RKRM: Libraries
- (page 312-315). In that example, the rkmmodelclass is a subclass of
- modelclass. The rkmmodelclass object inherits the behavior of
- modelclass, so its sends updates to its member objects. One feature
- rkmmodelclass adds to modelclass is that these objects maintain an
- internal integer value. If that value changes, the rkmmodelclass
- object propagates that change to its member objects.
-
- If one of the member objects happens to be a gadget object, changing
- the rkmmodelclass object's internal value may change the visual state
- of the gadgets. For the gadget's to update their visual state, they
- need the environment information from the GadgetInfo structure as
- well as the new internal value of the rkmmodelclass object. If an
- application used DoMethod() or SetAttrs() to set the rkmmodelclass
- object's internal value, the rkmmodelclass object would not get a
- GadgetInfo structure. When the rkmmodelclass object propagates the
- internal value change to its member objects, it has no environment
- information to pass on to its member objects. As a result, the
- member gadgets can not update their visual state directly. This is
- particularly annoying for a propgclass object, because the visual
- state of the propgclass object can depend on the rkmmodelclass
- object's integer value.
-
- DoGadgetMethodA() corrects this problem. It passes a pointer to a
- GadgetInfo structure for the window (or requester) you pass to it.
- If you plan on implementing new Boopsi methods that need a GadgetInfo
- structure in their Boopsi message, make sure the second long word of
- the Boopsi message is a pointer to the GadgetInfo structure.
- DoGadgetMethodA() assumes that every method (except for OM_NEW,
- OM_SET, OM_NOTIFY, and OM_UPDATE; see the next paragraph) expects a
- GadgetInfo pointer in that place.
-
- Iif you use DoGadgetMethodA() to send an OM_SET message to a Boopsi
- gadget, DoGadgetMethodA() passes a pointer to a GadgetInfo structure
- as the third long word in the Boopsi message. DoGadgetMethodA() is
- smart enough to know that the OM_SET method uses an opSet structure
- as its message, which has a pointer to a GadgetInfo structure as its
- third long word. DoGadgetMethodA() passes a GadgetInfo structure as
- the third parameter for the OM_NEW, OM_SET, OM_NOTIFY, and OM_UPDATE
- methods. For all other methods, like the gadgetclass methods,
- DoGadgetMethodA() passes a GadgetInfo structure as the second long
- word. For more information, see the V39 Autodoc for
- DoGadgetMethodA() and its varargs equivalent, DoGadgetMethod().
-
-
- Bounding Boxes for Gadgets
-
- Before Release 3, gadgets only had a select (or hit) box. This box
- is the area of the window that the user can click in to select the
- gadget. The select box limits certain gadgets because the gadget's
- imagery could lie outside of the gadget's hit box. For example, the
- hit box for a string gadget is the area that text appears when the
- user types into the gadget (see Figure 1). Many string gadgets have
- a border and a label, which the programmer sets using the Gadget
- structure's GadgetRender and GadgetText fields. The border and label
- imagery appears outside of the hit box.
-
-
- [Figure 1]
-
-
- The major disadvantage of a gadget's imagery being external to its
- hit box has to do with relative gadgets (these are sometimes referred
- to as GREL gadgets). Intuition positions one of these gadgets
- relative to the edge's of the gadget's window. When the window
- changes dimensions, Intuition repositions the gadget within the
- window. The gadget can also make its size relative to the window's
- dimensions.
-
- When Intuition resizes a window, it remembers which portions of the
- window's display sustained visual damage. When Intuition refreshes
- the visual state of the window, it only redisplays the parts of the
- window that sustained visual damage. When Intuition resizes a window
- that has a GREL gadget, Intuition erases the old gadget by erasing
- the hit box of the gadget and remembers that area as a region it will
- have to refresh. Intuition also figures out where the the new hit
- box will be and remembers that area as a region Intuition will have
- to refresh. Because Intuition will not erase or redraw any imagery
- that falls outside of the GREL gadget's hit box, Intuition will
- ignore any part of the gadget's label or border that is outside the
- hit box.
-
- To remedy this situation, Intuition added a bounding box to gadgets.
- If a gadget has a bounding box, Intuition uses the bounding box in
- place of the hit box when figuring out what areas to refresh. With a
- bounding box, a gadget can extend its hit area to encompass all of
- its imagery.
-
- The bounding box feature is not specific to Boopsi gadgets. Any
- Intuition gadget can have one. If the gadget doesn't supply a
- bounding box, Intuition will use the gadget's normal hit box as the
- bounding box, which yields the same result as previous versions of
- the OS.
-
- Adding the bounding box feature to Intuition gadgets required
- extending the Gadget structure. There is a new structure called
- ExtGadget that is a superset of the old Gadget structure (from
- <intuition/intuition.h>):
-
- struct ExtGadget
- {
- /* The first fields match struct Gadget exactly */
- struct ExtGadget *NextGadget; /* Matches struct Gadget */
- WORD LeftEdge, TopEdge; /* Matches struct Gadget */
- WORD Width, Height; /* Matches struct Gadget */
- UWORD Flags; /* Matches struct Gadget */
- APTR SpecialInfo; /* Matches struct Gadget */
- UWORD GadgetID; /* Matches struct Gadget */
- APTR UserData; /* Matches struct Gadget */
-
- /* These fields only exist under V39 and only if GFLG_EXTENDED is set */
- ULONG MoreFlags;
- WORD BoundsLeftEdge; /* Bounding extent for gadget, valid */
- WORD BoundsTopEdge; /* only if the GMORE_BOUNDS bit in */
- /* the MoreFlags field is set. The */
- WORD BoundsWidth; /* GFLG_RELxxx flags affect these */
- WORD BoundsHeight; /* coordinates as well. */
- };
-
-
- Intuition discerns a Gadget from an ExtGadget by testing the Flags
- field. If the GFLG_EXTENDED bit is set, the Gadget structure is
- really an ExtGadget structure. Intuition will use the bounding box
- only if the GMORE_BOUNDS bit in the ExtGadget.MoreFlags field is set.
-
- Gadgetclass supports an attribute called GA_Bounds that sets up a
- Boopsi gadget's bounding box. It expects a pointer to an IBox
- structure (from <intuition/intuition.h>) in the ti_Data field, which
- gadgetclass copies into the bounding box fields in the ExtGadget
- structure.
-
-
- Gadget Help
-
- Intuition V39 introduces a help system designed around Intuition
- gadgets. Window-based applications can elect to receive a new type
- of IDCMP message called IDCMP_GADGETHELP when the user positions the
- pointer over one of the window's gadgets. The pointer is over the
- gadget if the pointer is within the gadget's bounding box (which
- defaults to the gadget's hit box).
-
- Using the intuition.library function HelpControl(), an application
- can turn Gadget Help on and off for a window:
-
- VOID HelpControl(struct Window *my_win, ULONG help_flags);
-
- Currently, the only flag defined for the help_flags field is
- HC_GADGETHELP (from <intuition/intuition.h>). If the HC_GADGETHELP
- bit is set, HelpControl() turns on help for my_win, otherwise
- HelpControl() turns off gadget help for the window.
-
- When gadget help is on for the active window, Intuition sends
- IDCMP_GADGETHELP messages to the window's IDCMP port. Each time the
- user moves the pointer from one gadget to another, Intuition sends an
- IDCMP_GADGETHELP message about the new gadget. Intuition also sends
- an IDCMP_GADGETHELP message when the user positions the pointer over
- a gadgetless portion of the window, and when the user moves the
- pointer outside of the window. An application can find out what
- caused the IDCMP_GADGETHELP message by first examining the
- IntuiMessage's IAddress field. If IAddress is NULL, the pointer is
- outside of the window. If IAddress is the window address, the
- pointer is inside of the window, but not over any gadget. If
- IAddress is some other value, the user positioned the pointer over
- one of the window's gadgets and IAddress is the address of that
- gadget.
-
- To discern between the different system gadgets (window drag bar,
- window close gadget, etc.) an application has to check the GadgetType
- field of the gadget:
-
- #define GTYP_SYSTYPEMASK 0xF0 /* This constant did not appear in */
- /* earlier V39 include files. */
-
- sysgtype = ((struct Gadget *)imsg->IAddress)->GadgetType & GTYP_SYSTYPEMASK;
-
- The constant GTYP_SYSTYPEMASK (defined in <intuition/intuition.h>)
- corresponds to the bits of the GadgetType field used for the system
- gadget type. There are several possible values for sysgtype (defined
- in <intuition/intuition.h>):
-
- GTYP_SIZING Window sizing gadget
- GTYP_WDRAGGING Window drag bar
- GTYP_WUPFRONT Window depth gadget
- GTYP_WDOWNBACK Window zoom gadget
- GTYP_CLOSE Window close gadget
-
- If sysgtype is zero, IAddress is the address of an application's
- gadget.
-
- Not all gadget's will trigger an IDCMP_GADGETHELP event. Intuition
- will send gadget help events when the pointer is over a gadget with
- an extended Gadget structure (struct ExtGadget from
- <intuition/intuition.h>) and a set GMORE_GADGETHELP flag (from the
- ExtGadget.MoreFlags field).
-
- To set or clear this flag for a Boopsi gadget, an application can use
- the GA_GadgetHelp attribute. Setting GA_GadgetHelp to TRUE sets the
- flags and setting it to FALSE clears the flag. Only the OM_SET
- method applies to this gadgetclass attribute.
-
- To support gadget help, gadgetclass gained a new method called
- GM_HELPTEST. This method uses the same message structure as
- GM_HITTEST, struct gpHitTest (defined in <intuition/gadgetclass.h>),
- and operates similarly to GM_HITTEST. While a window is in help
- mode, when the user positions the pointer within the bounding box of
- a Boopsi gadget that supports gadget help, Intuition sends the gadget
- a GM_HELPTEST message.
-
- Like the GM_HITTEST method, the GM_HELPTEST method asks a gadget if a
- point is within the gadget's bounds. Like the GM_HITTEST method, the
- GM_HELPTEST method allows a Boopsi gadget to have a non-rectangular
- hit area (or in this case, a help area). If the point is within the
- gadget, the gadget uses one of two return codes. If the gadget
- returns a value of GMR_HELPHIT, Intuition places a value of 0xFFFF in
- the Code field of the IDCMP_GADGETHELP message. The gadget also has
- the option of using GMR_HELPCODE instead of GMR_HELPHIT.
- GMR_HELPCODE is a little peculiar as a return value. Although
- GMR_HELPCODE is 32 bits long, Intuition identifies GMR_HELPCODE using
- only its upper 16 bits. If the upper 16 bits of GM_HELPTEST's return
- value matches the upper 16 bits of GMR_HELPCODE, Intuition copies the
- lower word of the return value into the Code field of the
- IDCMP_GADGETHELP message. The Boopsi gadget is free to set the
- return value's lower word to any 16-bit value.
-
- If the point is not within the gadget's ``help spot'', the gadget
- returns GMR_NOHELPHIT. Intuition will then look under that gadget
- for more gadgets. If a gadget's dispatcher passes the GM_HELPTEST
- method on to the gadgetclass dispatcher, the gadgetclass dispatcher
- will always return GMR_HELPHIT.
-
- An application can put several windows in the same help group. This
- feature groups several windows so that as long as one of those
- windows is active, the application can receive IDCMP_GADGETHELP
- messages about all of those windows. For more information, See the
- HelpControl() Autodoc and the WA_HelpGroup section of the
- OpenWindow() Autodoc (both are in intuition.doc).
-
-
- Boopsi Gadgets and ScrollRaster()
-
- This section covers some fairly complicated aspects of Intuition
- Windows and how Intuition interacts with the Layers system. For a
- more in depth explanation, see the article, ``Optimized Window
- Refreshing'' from the July/August 1992 issue of Amiga Mail.
-
- Scrolling an Intuition display with ScrollRaster() is unlike many
- other rendering operations because it can damage a window layer.
- ScrollRaster() is both a rendering function and a layering function
- (ScrollRaster() is a graphics.library function, but it is aware of
- the Layers system). If window X overlaps window Y, scrolling window
- Y can scroll a portion of window Y out from underneath window X:
-
-
- [Figure 2a and 2b]
-
-
- For both smart refresh and super bitmap windows, this does not
- present a problem. Layers remembers what was underneath window X and
- restores that portion of the display when a layers operation reveals
- it. When a scrolling operation damages a smart refresh or super
- bitmap window, Layers repairs the display.
-
-
- What is Layer Damage?
-
- The Layers definition of ``damage'' is a little
- confusing. Looking at the illustration, two areas of
- window Y need to be refreshed: the area that used to be
- underneath window X, and the area that was scrolled
- into view at the bottom of window Y (the partially
- visible ``RSTUVWXY''). Layers considers only one of
- these areas to be ``damaged'', the area the was
- scrolled out from underneath window X. Layers considers
- it damaged because the damage was caused by the
- presence of another window layer. The task that called
- ScrollRaster() has no idea that there is an overlapping
- window layer, so it is up to Layers to account for that
- damage. On the other hand, the task that called
- ScrollRaster() knows that the area at the bottom of
- window Y needs refreshing, so the task knows to fix
- that area of the window. To Layers, damage is the area
- of a layer that needs refreshing as a result of layers
- operation.
-
-
- For a simple refresh window, Layers remembers which portion of the
- window layer is damaged. Layers does nothing to repair the damage.
- Layers leaves repairing the damage to Intuition. After performing a
- layers operation on a window (such as scrolling a portion of a
- window), Intuition must check if that operation caused layer damage
- (either to that window or other windows on the display).
-
- In Release 2, when Intuition told a scrolling Boopsi gadget to render
- itself, Intuition did not check for layer damage. If that gadget
- damaged the display with the ScrollRaster() function, Intuition did
- not repair that damage.
-
- As of Release 3.0, Intuition has a flag set aside in the MoreFlags
- field of the ExtGadget structure called GMORE_SCROLLRASTER (defined
- in <intuition/intuition.h>). If this flag is set, when the gadget
- damages the display with ScrollRaster() (or ScrollRasterBF()),
- Intuition redraws all GMORE_SCROLLRASTER gadgets in the damaged
- window. The class dispatcher should take care of setting this flag
- when creating the gadget in the OM_NEW method.
-
- ScrollRaster() is not the only function in Release 3 that can scroll
- a window's contents. For Release 3, the Intuition library gained a
- function specifically to scroll a window's raster. That function,
- ScrollWindowRaster(), is similar to ScrollRaster(), but
- ScrollWindowRaster() is Intuition-friendly. Boopsi gadgets must not
- use this function, they should use ScrollRaster() or ScrollRasterBF()
- instead. Also any applications that use GMORE_SCROLLRASTER gadgets
- must use ScrollWindowRaster() for scrolling. Note that gadgets
- supplied by third parties or Commodore may be GMORE_SCROLLRASTER
- gadgets. For more information on ScrollWindowRaster(), see its
- Autodoc.
-
-
- Smart Layout Gadgets
-
- Prior to Release 3, Intuition took care of laying out GREL gadgets
- whenever the dimensions of the window change. This was a limitation
- for a GREL Boopsi gadget that wants to perform its own layout.
- Because Intuition didn't tell the Boopsi gadget that the window's
- dimensions changed, the gadget cannot react to the change.
-
- As of Release 3, Intuition uses a new gadget method called GM_LAYOUT
- to tell a GREL Boopsi gadget that its window's dimensions have
- changed. The GM_LAYOUT method uses the gpLayout structure (defined
- in <intuition/gadgetclass.h>) as its message:
-
- struct gpLayout
- {
- ULONG MethodID;
- struct GadgetInfo *gpl_GInfo;
- ULONG gpl_Initial; /* This field is non-zero if this method was invoked
- * during AddGList() or OpenWindow(). zero if this
- * method was invoked during window resizing.
- */
- };
-
- For GREL gadgets, Intuition sends a GM_LAYOUT message just after
- erasing the gadget's bounding box. Intuition does not touch the
- values of the gadget's bounding box or hit box, it lets the gadget
- handle recalculating these values. Thee gadget can lay itself out
- based on the new window (or requester) dimensions found in the
- GadgetInfo structure passed in the GM_LAYOUT message (gpl_GInfo from
- the gpLayout structure). Intuition also adds the old and new
- bounding box of the gadget to the window's damaged regions so that
- the gadget will appear is its new position. The gadget must not
- perform any rendering inside the GM_LAYOUT method. Intuition will
- send a GM_RENDER message to the gadget when its time to redraw the
- gadget in its new position.
-
- There are two cases where Intuition sends a GM_LAYOUT message:
-
- When the gadget's window is resized
- When Intuition adds the gadget to a window
-
- There are two ways for a window to gain gadgets. An application can
- explicitly add gadgets using the AddGList() function. The window can
- also gain gadgets during it initialization in the OpenWindow() call.
-
- For most GREL Boopsi gadgets, Intuition expects the values in the
- LeftEdge, TopEdge, Width, and Height fields to follow the existing
- convention for regular GREL gadgets. Each of these fields has a flag
- in the Gadget.Flags field (GFLG_RELRIGHT, GFLG_RELBOTTOM,
- GFLG_RELWIDTH, and GFLG_RELHEIGHT, respectively). If that field's
- flag is set, Intuition expects the value in that field to be relative
- to either the window border or the window dimensions. For example,
- if GFLG_RELRIGHT is set, Intuition expects the value in the gadget's
- LeftEdge field to be relative to the right window border.
-
- There is a special kind of GREL Boopsi gadget called a custom
- relativity gadget. For this type of gadget, Intuition expects the
- values in the LeftEdge, TopEdge, Width, and Height fields to be
- absolute measurements, just like the values Intuition expects in
- these fields for non-GREL gadgets.
-
- Setting the GFLG_RELSPECIAL bit in the Gadget.Flags field marks the
- gadget as a custom relativity gadget. The best way to set this bit
- is by setting the GA_RelSpecial attribute to TRUE when creating the
- gadget.
-
-
- Disabled Imagery
-
- Certain gadget types support using a Boopsi Image as its imagery.
- These gadget types include the non-Boopsi boolean gadget, the
- frbuttonclass gadget, and the buttongclass gadget (This can also
- include private gadget classes that support the GA_Image attribute).
- The Gadget structure contains a field called GadgetRender which can
- point to a Boopsi Image object (the GFLG_GADGIMAGE bit in the
- Gadget.Flags field should also be set, see the``Intuition Gadgets''
- chapter of the RKRM:Libraries for more information). Intuition uses
- this image as the gadget's imagery.
-
- When a gadget uses this scheme for its imagery, Intuition sends
- IM_DRAW (and IM_DRAWFRAME) messages to the image object. These
- imageclass methods not only tell a Boopsi image to render itself,
- they also tell the image which state to draw itself. Some examples
- of image states include normal, selected, and disabled.
-
- Prior to Release 3, when Intuition sent a draw message to one of
- these images, it only used the normal and selected states. If the
- image was disabled, Intuition told the image to draw itself as normal
- or selected and would render the standard ``ghosted'' imagery over
- the gadget.
-
- Under Release 3, Intuition will use the disabled state as well, but
- only if the gadget's image object supports it. When Intuition adds
- the gadget to a window, Intuition tests the IA_SupportsDisabled
- attribute of the gadget's image object. This imageclass attribute
- was introduced in Release 3. If this attribute is TRUE, the image
- supports disabled imagery (both the IDS_DISABLED and
- IDS_SELECTEDDISABLED states), so Intuition sets the GFLG_IMAGEDISABLE
- flag in the Gadget structure's Flags field. Intuition uses this flag
- to tell if it should use the image's disabled state in the
- IM_DRAW/IM_DRAWFRAME message.
-
- As the IA_SupportsDisabled attribute is a fixed property of an image
- object, it is only accessible using the OM_GET method. An
- application cannot set it or clear it.
-
-
- Frameiclass Frame Types
-
- For Release 3, the Boopsi image class frameiclass acquired a new
- attribute, IA_FrameType. This attribute allows applications to
- choose a frame style for a frame image. Currently there are four
- styles available:
-
- FRAME_DEFAULT - This is the default frame which was the only
- available frame in V37. It has thin edges.
-
- FRAME_BUTTON - This is the imagery for the standard button
- gadget. It has thicker sides and nicely edged corners.
-
- FRAME_RIDGE - This is a ridge commonly used by standard string
- gadgets. When recessed (using the frameiclass attribute
- IA_Recessed), this image appears as a groove. Applications and
- utilities commonly use the recessed image to visually group
- objects on the display.
-
- FRAME_ICONDROPBOX - This broad ridge is the system standard
- imagery for icon ``drop boxes'' inside of an AppWindow (see the
- ``Workbench and Icon Library'' chapter of the RKRM:Libraries for
- more information on AppWindows). The recessed version has no
- standard purpose.
-
-
- [Figure 3]
-
-
-
- Additions to Sysiclass
-
- The class of system images, sysiclass, gained two new images for
- Release 3, a menu check mark image and an Amiga key image
- (respectively, MENUCHECK and AMIGAKEY from
- <intuition/imageclass.h>):
-
-
- [Figure 4]
-
-
-
- This class also gained a new attribute called
- SYSIA_ReferenceFont. This attribute, which is only accessible
- with the OM_NEW method, points to a TextFont structure. The
- MENUCHECK and AMIGAKEY images will use this font to figure out
- how large to make the image. This attribute overrides the
- SYSIA_DrawInfo font and SYSIA_Size attributes when calculating
- the dimensions of the image.
-
-
- About the Example
-
- The example at the end of this article, relative.c, uses three
- features mentioned in this article. The example implements a
- private subclass of gadgetclass. The new class utilizes the
- frameiclass IA_FrameType attribute to create a button gadget.
- The class also takes advantage of the custom relativity feature.
- The example opens a window placing one of these gadgets in the
- middle of the window, sizing the gadget relative to the window's
- dimensions.
-
- The example also illustrates the gadget help feature of
- Intuition. When the private class dispatcher receives a
- GM_HELPTEST message, it returns the bitwise AND of GMR_HELPCODE
- and the value 0xC0DE. When the example receives an
- IDCMP_GADGETHELP message at the window's message port, the
- example examines the message to find out what object triggered
- the help message and printf()s the results.
-